<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./style.css">
    <link rel="stylesheet" href="./json.css">
</head>

<body>
    <h1>cat cook soda powder walnut heart deliver wheel shy club arch inside</h1>
    <div id="app">
        <h1>接入网络信息</h1>
        <h1>New Block: {{blockNumber}}</h1>
        <p>MetaMask Account: {{nowAccount}}</p>
        <p>
        <h3>network information </h3>
        chainId: {{netInfo.chainId}}<br>
        name: {{netInfo.netName}}<br>
        ensAddress: {{netInfo.ensAddress}}<br>
        </p>
        <div>
            <h3>转账</h3>
            <input type="text" placeholder="地址" id="to-address" list="accounts">
            <datalist id="accounts">
                <option value="0xC32D5C700cEdc1F30b889a84fE3f64e3d5930f0E"></option>
                <option value="0x24c50401e9c45D9F07190F95D2cde6e558b02650"></option>
                <option value="0xD54E0c83b62beF185AE283898f71793999531D42"></option>
            </datalist>
            <input type="text" placeholder="金额" id="amount">ETH <br>
            <button @click="transfer()">send</button>
        </div>
        <div>
            <h3>部署合约</h3>
            <input type="text" placeholder="合约名称" v-model="contract.name" list="contract-name">
            <input type="text" placeholder="合约参数(JSON数组)" v-model="contract.para">
            <button @click="deployContract()">部署</button>
        </div>
        <div>
            <h3>执行合约方法</h3>
            <select v-model="methodType" title="方法类型">
                <option value="">view</option>
                <option value="1">writable</option>
                <option value="2">payable</option>
            </select>
            <input type="text" placeholder="合约地址" v-model="contract.address">
            <input type="text" placeholder="合约名称" v-model="contract.name" list="contract-name">
            <datalist id="contract-name">
                <option value="ArtMarket"></option>
                <option value="Auction"></option>
            </datalist>
            <input type="text" placeholder="方法名" v-model="method" list="contract-method">
            <datalist id="contract-method">
                <option value="name"></option>
                <option value="infos"></option>
                <option value="registerAutor"></option>
                <option value="purchase"></option>
                <option value="ownerOf"></option>
                <option value="bid"></option>
                <option value="withdraw"></option>
            </datalist>
            <input type="text" placeholder="参数(JSON数组)" v-model="paras">
            <input v-if="methodType=='2'" type="text" placeholder="value" v-model="value">
            <button @click="execute()">execute</button>
            <pre v-html="returnValue"></pre>
        </div>
        <div>
            <h3>交易信息查看</h3>
            <input type="text" placeholder="transactionHash" v-model="transactionHash" list="tx-hash"><br>
            <datalist id="tx-hash">
                <option value="0x251df9a89b66d5cffd624da5f604074a980b0641c5cf822c66e563d8dd715ce0"></option>
                <option value="0x4bb93237973966e880b9096e66d1ec9f65de0e9cd7f99a67244999a266b14d62"></option>
            </datalist>
            <pre v-html="transactionJSON"></pre>
        </div>
        <div>
            <h3>账户信息查看</h3>
            <input type="text" placeholder="账户地址" v-model="address" list="accounts"><br>
            <p>Balance: {{balance}} eth</p>
            <p>TransactionCount: {{transactionCount}} </p>
        </div>
        <div>
            <h3>合约事件过滤</h3>
            <input type="text" placeholder="合约地址" v-model="this.filter.address" style="width:26%" list="filter-address">
            <datalist id="filter-address">
                <option value="0x1b3e46dfcff3857388d59faaf4d017e5205b80e6"></option>
                <option value="0x69B9C98e8D715C25B330d0D4eB07e68CbB7F6CFC"></option>
            </datalist>
            <input type="text" placeholder="from" v-model="this.filter.fromBlock" style="width:26%"
                list="filter-BlockNumber">
            <datalist id="filter-BlockNumber">
                <option>14203000</option>
                <option>14204000</option>
                <option value="14260000"></option>
                <option value="14261000"></option>
                <option value="latest"></option>
            </datalist>
            <input type="text" placeholder="to" v-model="this.filter.toBlock" style="width:26%"
                list="filter-BlockNumber">
            <button @click="addTopic()">add topic</button>
            <button @click="getLogs()">get logs</button>
            <div>
                <template v-for="item,index in filter.topics">
                    <input type="text" placeholder="topic" v-model="this.filter.topics[index]" list="filter-topics">
                    <datalist id="filter-topics">
                        <option>Transfer(address,address,uint256)</option>
                        <option>Approval(address,address,uint256)</option>
                    </datalist>
                    <button @click="removeTopic(index)">remove</button>
                </template>
            </div>
            <pre v-html="logs"></pre>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.25.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
    <script src="https://cdn.jsdelivr.net/npm/ethers@5.5.4/dist/ethers.umd.min.js"></script>
    <script src="./utils.js"></script>
    <script>
        checkEnv();
        var contract = null;
        var provider = new ethers.providers.Web3Provider(ethereum);
        let fillNetWorkInfo = (ctx) => {
            provider.getNetwork().then(x => {
                ctx.chainId = x.chainId
                ctx.netName = x.name
                ctx.ensAddress = x.ensAddress || 'No ENS service'
            })
        }
    </script>
    <script src="./json.js"></script>
    <script src="./deploy.js"></script>
    <script>
        "use strict";
        const conf = {
            data() {
                return {
                    value: null,
                    method: null,
                    paras: null,
                    methodType: '',
                    returnValue: null,
                    contract: {
                        name: null,
                        para: null,
                        address: null,
                    },
                    netInfo: {
                        chainId: 0,
                        netName: 0,
                        ensAddress: 0,
                    },
                    _count: 0,
                    _balance: 0,
                    address: null,
                    transactionHash: null,
                    transaction: '{}',
                    filter: {
                        address: '',
                        fromBlock: '',
                        toBlock: '',
                        topics: [null],
                    },
                    logs: '{}',
                    blockNumber: 0,
                    nowAccount: 'Not able to get accounts',
                }
            },
            computed: {
                transactionCount() {
                    if (!isAccountAddress(this.address)) return this._count
                    provider.getTransactionCount(this.address).then(x => this._count = x);
                    return this._count
                },
                balance() {
                    if (!isAccountAddress(this.address)) return this._balance
                    provider.getBalance(this.address).then(x => { this._balance = x / 1000000000000000000 })
                    return this._balance
                },
                transactionJSON() {
                    if (!isHash(this.transactionHash)) return this.transaction
                    provider.getTransaction(this.transactionHash).then(x => this.transaction = x ? renderJson(x) : '{}');
                    return this.transaction
                },
            },
            created() {
                let updatedNetWork = () => {
                    fillNetWorkInfo(this.netInfo)
                    ethereum.request({ method: 'eth_blockNumber' })
                        .then(x => this.blockNumber = parseInt(x, 16))
                    provider.on('block', x => this.blockNumber = x)
                }
                updatedNetWork()
                ethereum.on('chainChanged', networkId => {
                    console.log('chainChanged');
                    // 更新 provider
                    provider = new ethers.providers.Web3Provider(ethereum);
                    updatedNetWork()
                });


                let handler = (accounts => this.nowAccount = accounts[0] || 'Not able to get accounts')
                ethereum.request({ method: 'eth_requestAccounts' }).then(handler)
                ethereum.on('accountsChanged', handler)
            },
            methods: {
                transfer() {
                    let amountETH = ethers.utils.parseEther($("#amount").val()).toHexString()
                    ethereum.request({
                        method: 'eth_sendTransaction',
                        params: [
                            {
                                from: this.nowAccount,
                                to: $("#to-address").val(),
                                value: amountETH,
                            },
                        ],
                    })
                        .then((txHash) => this.transactionHash = txHash)
                        .catch((error) => console.error);
                },



                execute() {
                    let _exec = () => {
                        let paras = JSON.parse(this.paras) || []
                        let overrides = {}
                        switch (this.methodType) {
                            case '2':
                                overrides = {
                                    value: ethers.utils.parseEther(this.value || '0')
                                };
                            case '1':
                                const signer = provider.getSigner();
                                let contractWithSigner = contract.connect(signer);
                                contractWithSigner[this.method].call(this, ...paras, overrides)
                                    .then(tx => {
                                        console.log('发起交易:', tx.hash, '...');
                                        this.transactionHash = tx.hash;
                                        tx.wait().then(x => {
                                            this.returnValue = renderJson(x || {})
                                            console.log(tx.hash, '交易成功');
                                        })
                                    })
                                    .catch(err => {
                                        console.log(err);
                                        alert(err.message);
                                    })
                                break;
                            default:
                                contract[this.method].call(this, ...paras)
                                    .then(x => {
                                        this.returnValue = renderJson(x || {})
                                    })
                                    .catch(err => {
                                        console.log(err);
                                        alert(err.message);
                                    })
                                break;
                        }
                    }
                    if (!contract || contract.address != this.contract.address) {
                        // 创建新的合约对象
                        if (this.contract.name) {
                            findContractAt(this.contract.name, this.contract.address)
                                .then(x => {
                                    contract = x;
                                    _exec();
                                })
                        } else {
                            alert('请填写合约名称');
                        }
                        return;
                    }
                    _exec();
                },
                deployContract() {
                    if (this.contract.name) {
                        let para = JSON.parse(this.contract.para) || []
                        deploy(this.contract.name, para)
                            .then(con => {// 注入到全局变量 contract 
                                contract = con;
                                this.contract.address = con.address;
                            })
                            .catch(err => {
                                alert(err.message)
                                console.log('deploy error:\n', err)
                            })
                    } else {
                        alert('请输入合约名称')
                    }
                },
                addTopic() {
                    this.filter.topics.push(null);
                },
                removeTopic(index) {
                    this.filter.topics.splice(index, 1);
                },
                getLogs() {
                    let filter = { ...this.filter };
                    let topics = filter.topics.filter(x => x)
                    if (topics.length == 0) {
                        alert('请输入topic')
                    } else {
                        filter.topics = topics.map(x => ethers.utils.id(x.trim()))
                        filter.address = filter.address.trim()
                        filter.fromBlock = isNaN(filter.fromBlock) ? filter.fromBlock : Number(filter.fromBlock)
                        filter.toBlock = isNaN(filter.toBlock) ? filter.toBlock : Number(filter.toBlock)
                        provider.getLogs(filter).then(x => {
                            if (x) this.logs = renderJson(x)
                            else {
                                console.log('无事件');
                                this.logs = '[]'
                            }
                        });
                    }
                },
            },
        }
        var app = Vue.createApp(conf).mount('#app')
    </script>
    <!-- 
        [a1,a2] = accounts 
        a = await ArtMarket.new({from:a1})
        a.address
        r = await a.registerAutor(a1,'MyNFT',{from:a1})
        r = await a.approve(a2,1,{from:a1})
     -->
</body>

</html>